package cate.game.role.mall;

import cate.common.table.d.GDMall;
import cate.game.GameBody;

import java.util.*;
import java.util.stream.Collectors;

public class RefreshTimeCheck {
    /** 判断能否刷新 */
    public static boolean isRefresh(GameBody game, long lastTime, String config) {
        return game.time.now() >= nextRefreshTime(lastTime, config);
    }

    /** 计算下次刷新时间 */
    public static long nextRefreshTime(long lastTime, String config) {
        String[] configs = config.split(":");
        Byte timeType = Byte.parseByte(configs[0]);
        int num = Integer.parseInt(configs[1]);
        if (configs.length == 2) {
            // 不带开始时间时，直接根据上次刷新时间加上刷新周期算出下次刷新时间
            return nextRefreshTime(lastTime, timeType, num);
        } else {
            String start = configs[2];
            List<Integer> starts =
                    Arrays.stream(start.split(","))
                            .map(Integer::parseInt)
                            .collect(Collectors.toList());
            List<Long> nextTimes = new ArrayList<>();
            for (Integer startTime : starts) {
                nextTimes.add(nextRefreshTime(lastTime, timeType, num, startTime));
            }
            return Collections.min(nextTimes);
        }
    }

    /** 没有周期开始时间时，计算下次刷新时间 */
    private static long nextRefreshTime(long lastTime, Byte type, int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(lastTime);
        switch (type) {
            case GDMall.RefreshTimeType.T1:
                calendar.add(Calendar.HOUR_OF_DAY, num);
                return calendar.getTimeInMillis();
            case GDMall.RefreshTimeType.T2:
                calendar.add(Calendar.DATE, num);
                return calendar.getTimeInMillis();
            case GDMall.RefreshTimeType.T3:
                calendar.add(Calendar.WEEK_OF_YEAR, num);
                return calendar.getTimeInMillis();
            case GDMall.RefreshTimeType.T4:
                calendar.add(Calendar.MONTH, num);
                return calendar.getTimeInMillis();
            default:
                return 0L;
        }
    }

    /** 有开始时间时，计算下次刷新时间 */
    private static long nextRefreshTime(long lastTime, Byte type, int num, int start) {
        Calendar last = Calendar.getInstance();
        last.setTimeInMillis(lastTime);
        last.set(Calendar.SECOND, 0);

        switch (type) {
                // 1:1:10,20,30   每小时的10分,20分,30分刷新
            case GDMall.RefreshTimeType.T1:
                if (last.get(Calendar.MINUTE) >= start) {
                    last.add(Calendar.HOUR_OF_DAY, num);
                }
                last.set(Calendar.MINUTE, start);
                return last.getTimeInMillis();
                // 2:1:1,9,19   每天的1点,9点,19点刷新
            case GDMall.RefreshTimeType.T2:
                if (last.get(Calendar.HOUR_OF_DAY) >= start) {
                    last.add(Calendar.DAY_OF_WEEK, num);
                }
                last.set(Calendar.MINUTE, 0);
                last.set(Calendar.HOUR_OF_DAY, start);
                return last.getTimeInMillis();
                // 3:1:1,3,5   每周的一、三、五 零点刷新
            case GDMall.RefreshTimeType.T3:
                if (last.get(Calendar.DAY_OF_WEEK) >= parseDayOfWeek(start)) {
                    last.add(Calendar.WEEK_OF_YEAR, num);
                }
                last.set(Calendar.MINUTE, 0);
                last.set(Calendar.HOUR_OF_DAY, 0);
                last.set(Calendar.DAY_OF_WEEK, parseDayOfWeek(start));
                return last.getTimeInMillis();
                // 4:1:5,15,20   每月的5、15、20号零点刷新
            case GDMall.RefreshTimeType.T4:
                if (last.get(Calendar.DAY_OF_MONTH) >= start) {
                    last.add(Calendar.MONTH, num);
                }
                last.set(Calendar.MINUTE, 0);
                last.set(Calendar.HOUR_OF_DAY, 0);
                last.set(Calendar.DATE, start);
                return last.getTimeInMillis();
            default:
                return System.currentTimeMillis();
        }
    }

    /** Calendar中每周的第一天是周日，需要把模板表中填的日期进行转换 */
    private static int parseDayOfWeek(int day) {
        int temp = day + 1;
        return temp > 7 ? 1 : temp;
    }
}
